package com.mk.legoscans2.data;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import android.graphics.Bitmap;
import android.sax.Element;
import android.sax.EndElementListener;
import android.sax.EndTextElementListener;
import android.sax.RootElement;

import com.mk.legoscans2.Scan;
import com.mk.legoscans2.Utils;

public class WebApiRepository extends SaxFeedParser implements ApiRepository {

	private ErrorReoportingSerivice _errorReoportingSerivice;
	private String _domain;
	private int _port;

	public WebApiRepository(ErrorReoportingSerivice errorReoportingSerivice, String domain, int port)
	{
		_errorReoportingSerivice = errorReoportingSerivice;
		_domain = domain;
		_port = port;
	}
	
	public Scan getScan(String id) {
		final Scan s = new Scan();
		
		RootElement root = new RootElement("ScanInfo");
		setUpScanItemElementListeners(root, s);
        
        URL url;
		try {
			url = new URL("http://" + _domain + ":" + _port + "/scan/xml/" + id + "?source=android");
		} catch (MalformedURLException ex) {
			throw new RuntimeException(ex);
		}
        
		if(!ExecuteParser(url, root))
			return null;
        
        return s;
	}
	
	public List<Scan> getScans() {
		URL url;
		try {
			url = new URL("http://" + _domain + ":" + _port + "/scans/xml?source=android");
		} catch (MalformedURLException ex) {
			throw new RuntimeException(ex);
		}
		
		return getScansGeneric(url);
	}
	
	public List<Scan> getScansByTheme(String theme) {
		URL url;
		try {
			URI uri = new URI("http", null, _domain, _port, "/ScansByTheme/xml/" + Utils.getUrlSafeTheme(theme), "source=android", null);
			url = new URL(uri.toASCIIString());
		} catch (URISyntaxException e) {
			throw new RuntimeException(e);
		} catch (MalformedURLException e) {
			throw new RuntimeException(e);
		}
		
		return getScansGeneric(url);
	}
	
	public List<String> getThemes() {
		final List<String> t = new ArrayList<String>();
		
		RootElement root = new RootElement("Themes");
		root.getChild("string").setEndTextElementListener(new EndTextElementListener() {
			public void end(String body) {
				t.add(body);
			}
		});
		
		URL url;
		try {
			url = new URL("http://" + _domain + ":" + _port + "/Themes/xml?source=android");
		} catch (MalformedURLException ex) {
			throw new RuntimeException(ex);
		}
		
		if(!ExecuteParser(url, root))
			return null;
		
		return t;
	}
	
	public Bitmap getImage(String scanId, int page) {
		URL url;
		try {
			url = new URL("http://" + _domain + ":" + _port + "/Image/" + scanId + "/" + page + "?source=android");
		} catch (MalformedURLException ex) {
			throw new RuntimeException(ex);
		}
		
		Bitmap bmp = Utils.getImageBitmapFromUrl(url);
		
		//if there was a problem fetching the Bitmap, try report the error so it might me fixed in the future
		if(bmp == null)
			_errorReoportingSerivice.reportBrokenImage(scanId, page);
		
		return bmp;
	}
	
	public List<Scan> getScansByQuery(String query) {
		URL url;
		try {
			URI uri = new URI("http", null, _domain, _port, "/scansbyquery/xml/" + Utils.getUrlSafeTheme(query.trim()), "source=android", null);
			url = new URL(uri.toASCIIString());
		} catch (URISyntaxException e) {
			throw new RuntimeException(e);
		} catch (MalformedURLException e) {
			throw new RuntimeException(e);
		}
		
		return getScansGeneric(url);
	}
	
	public List<Scan> getScansByIds(List<String> scanIds) {
		ArrayList<Scan> scans = new ArrayList<Scan>();
		for (String scanId : scanIds) {
			scans.add(getScan(scanId));
		}
		
		return scans;
	}
	
	private List<Scan> getScansGeneric(URL url)
	{
		final List<Scan> scans = new ArrayList<Scan>();
		final Scan s = new Scan();
		
		RootElement root = new RootElement("Scans");
		Element item = root.getChild("ScanInfo");
		
		item.setEndElementListener(new EndElementListener() {
			public void end() {
				scans.add(s.clone());
				s.reset();
			}
		});
		
		setUpScanItemElementListeners(item, s);

		if(!ExecuteParser(url, root))
			return null;
		
		return scans;
	}
	
	private void setUpScanItemElementListeners(Element scanItemElement, final Scan s)
	{
		scanItemElement.getChild("ScanId").setEndTextElementListener(new EndTextElementListener() {
			public void end(String body) {
				s._scanId = body;
			}
		});
        
		scanItemElement.getChild("BoxId").setEndTextElementListener(new EndTextElementListener() {
			public void end(String body) {
				s._boxNumber = Integer.parseInt(body);
			}
		});
        
		scanItemElement.getChild("Name").setEndTextElementListener(new EndTextElementListener() {
			public void end(String body) {
				s._name = body;
			}
		});
        
		scanItemElement.getChild("Theme").setEndTextElementListener(new EndTextElementListener() {
			public void end(String body) {
				s._theme = body;
			}
		});
        
		scanItemElement.getChild("Year").setEndTextElementListener(new EndTextElementListener() {
			public void end(String body) {
				s._year = (body != null && body != "") ? Integer.parseInt(body) : null;
			}
		});
        
		scanItemElement.getChild("PageCount").setEndTextElementListener(new EndTextElementListener() {
			public void end(String body) {
				s._pageCount = Integer.parseInt(body);
			}
		});
		
		scanItemElement.getChild("DiscSize").setEndTextElementListener(new EndTextElementListener() {
			public void end(String body) {
				s._size = Long.parseLong(body);
			}
		});
	}
}
